package com.shop.rabbit.business;

import cn.common.constant.EntrustConstant;
import cn.common.utils.DateUtil;
import cn.model.*;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shop.rabbit.mapper.BalanceMapper;
import com.shop.rabbit.mapper.EntrustHistoryMapper;
import com.shop.rabbit.mapper.EntrustMapper;
import com.yuan.common.redis.constant.CacheConstants;
import com.yuan.common.redis.lock.RedisDistributedLock;
import com.yuan.common.redis.service.RedisRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

@Slf4j
@Component
public class EntrustBalanceBusiness {
    @Autowired
    private EntrustMapper entrustMapper;
    @Autowired
    private EntrustHistoryMapper entrustHistoryMapper;
    @Autowired
    private RedisRepository redisRepository;
    @Autowired
    private BalanceMapper balanceMapper;
    public void execute(String message) {
        try {
            System.out.println("撮合结果进行资产更新,扣除手续费:"+message);
            EntrustBalance entrustBalance = JSONObject.parseObject(message,EntrustBalance.class);
            String pairsName = entrustBalance.getPairsName();
            BigDecimal price = entrustBalance.getPrice();
            BigDecimal count = entrustBalance.getCount();
            if(!entrustBalance.getActiveOrder().contains("robot")){
                log.info("成交信息:" + message);
                //查询交易单
                Entrust entrust = entrustMapper.selectById(entrustBalance.getActiveOrder());
                if(entrust == null){
                    entrust = new Entrust();
                    EntrustHistory entrustHistory = entrustHistoryMapper.selectById(entrustBalance.getActiveOrder());
                    BeanUtils.copyProperties(entrustHistory,entrust);
                }else {
                    entrust.setSurplusCount(entrust.getSurplusCount().subtract(count));
                    if(!entrustBalance.getPassiveOrder().contains("robot")){//判断被交易方是否是机器人
                        Entrust passiveEntrust = entrustMapper.selectById(entrustBalance.getPassiveOrder());//被交易方是否存在
                        if(passiveEntrust == null){
                            EntrustHistory entrustHistory = entrustHistoryMapper.selectById(entrustBalance.getPassiveOrder());//查询记录对应的id 用户
                            if(entrustHistory != null){
                                entrust.setMatchMember(entrustHistory.getMember());
                            }
                        }else {
                            //设置撮合用户
                            entrust.setMatchMember(passiveEntrust.getMember());
                        }
                    }else {
                        entrust.setMatchMember("robot");
                    }
                    entrust.setMatchCount(entrust.getMatchCount().add(count));
                    entrust.setMatchPrice(price);
                    entrust.setMethodType(EntrustConstant.Method_Type.ACTIVE);
                    entrust.setMatchFee(entrust.getMatchCount().multiply(entrust.getMatchPrice()));
                    updateOrderBalanceA(entrust,entrustBalance);
                }
            }

            if (!entrustBalance.getPassiveOrder().contains("robot")) {

                Entrust passiveEntrust = entrustMapper.selectById(entrustBalance.getPassiveOrder());
                if (passiveEntrust == null) {
                    passiveEntrust = new Entrust();
                    EntrustHistory entrustHistory = entrustHistoryMapper.selectById(entrustBalance.getPassiveOrder());
                    BeanUtils.copyProperties(entrustHistory, passiveEntrust);
                }
                // 被动方
                if (passiveEntrust != null) {
                    passiveEntrust.setSurplusCount(passiveEntrust.getSurplusCount().subtract(entrustBalance.getCount()));
                    // 主动方
                    if (!entrustBalance.getActiveOrder().contains("robot")) {
                        Entrust activeEntrust = entrustMapper.selectById(entrustBalance.getActiveOrder());
                        if (activeEntrust == null) {
                            EntrustHistory entrustHistory = entrustHistoryMapper.selectById(entrustBalance.getActiveOrder());
                            passiveEntrust.setMatchMember(entrustHistory.getMember());
                        } else {
                            passiveEntrust.setMatchMember(activeEntrust.getMember());
                        }

                    } else {
                        passiveEntrust.setMatchMember("robot");
                    }
                    passiveEntrust.setMatchCount(passiveEntrust.getMatchCount().add(entrustBalance.getCount()));
                    passiveEntrust.setMethodType(EntrustConstant.Method_Type.PASSIVE);
                    passiveEntrust.setMatchPrice(entrustBalance.getPrice());
                    passiveEntrust.setMatchFee(passiveEntrust.getMatchCount().multiply(passiveEntrust.getMatchPrice()));
                    updateOrderBalanceP(passiveEntrust, entrustBalance);
                }
            }
            // redis
            long timestamp = new Date().getTime();
            // 一分钟
            Long oneMinuteTimestamp = DateUtil.minuteTimestamp(timestamp, 1);
            String oneMinute = "1m";
            redisKline(pairsName, price, count, oneMinuteTimestamp, oneMinute);
            // 五分钟
            Long fiveMinuteTimestamp = DateUtil.minuteTimestamp(timestamp, 5);
            String fiveMinute = "5m";
            redisKline(pairsName, price, count, fiveMinuteTimestamp, fiveMinute);
            // 15分钟
            Long fifteenMinuteTimestamp = DateUtil.minuteTimestamp(timestamp, 15);
            String fifteenMinute = "15m";
            redisKline(pairsName, price, count, fifteenMinuteTimestamp, fifteenMinute);
            // 30分钟
            Long thirtyMinuteTimestamp = DateUtil.minuteTimestamp(timestamp, 30);
            String thirtyMinute = "30m";
            redisKline(pairsName, price, count, thirtyMinuteTimestamp, thirtyMinute);
            // 1小时
            Long oneHourTimestamp = DateUtil.hourTimestamp(timestamp);
            String oneHour = "1h";
            redisKline(pairsName, price, count, oneHourTimestamp, oneHour);
            // 一天
            Long oneDayTimestamp = DateUtil.dayTimestamp(timestamp);
            String oneDay = "1d";
            redisKline(pairsName, price, count, oneDayTimestamp, oneDay);
            // 一星期
            Long oneWeekTimestamp = DateUtil.weekTimestamp(timestamp, 1);
            String oneWeek = "1w";
            redisKline(pairsName, price, count, oneWeekTimestamp, oneWeek);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    private void redisKline(String pairsName, BigDecimal price, BigDecimal count, Long timestamp, String time) {
        String key = CacheConstants.KLINE_KEY + time + CacheConstants.SPLIT + pairsName;
        Set<String> oneMinute = redisRepository.zsetRevRang(key, 0, 0);
        Iterator<String> oneMinuteIt = oneMinute.iterator();
        Kline kline = new Kline();
        if (oneMinuteIt.hasNext()) {
            String next = oneMinuteIt.next();
            Kline redisKline = JSONObject.parseObject(next, Kline.class);
           // Kline redisKline = JSONObject.toJavaObject(jsonObject, Kline.class);
            if (timestamp.equals(redisKline.getTime())) {
                if (price.compareTo(redisKline.getHigh()) > 0) {
                    kline.setHigh(price);
                } else {
                    kline.setHigh(redisKline.getHigh());
                }
                if (price.compareTo(redisKline.getLow()) < 0) {
                    kline.setLow(price);
                } else {
                    kline.setLow(redisKline.getLow());
                }
                kline.setOpen(redisKline.getOpen());
                kline.setClose(price);
                kline.setTime(redisKline.getTime());
                kline.setVolume(redisKline.getVolume().add(count));
            } else {
                kline.setTime(timestamp);
                kline.setVolume(count);
                kline.setClose(price);
                kline.setLow(price);
                kline.setHigh(price);
                kline.setOpen(price);
            }
        } else {
            kline.setVolume(count);
            kline.setClose(price);
            kline.setLow(price);
            kline.setHigh(price);
            kline.setOpen(price);
            kline.setTime(timestamp);
        }
        redisRepository.zsetRmByScore(key, timestamp);
        Boolean bool = redisRepository.zsetAdd(key, JSONObject.toJSONString(kline), timestamp);
        if (!bool) {
            log.error("redis存储失败");
        }
    }

    private void updateOrderBalanceA(Entrust activeEntrust, EntrustBalance entrustBalance) {
           RedisDistributedLock redisDistributedLock =  new RedisDistributedLock(redisRepository.getRedisTemplate());
          boolean lock_coin = redisDistributedLock.lock(CacheConstants.MEMBER_BALANCE_COIN_KEY + activeEntrust.getMember(),10000,50,100);
          if(lock_coin){
              BigDecimal price = entrustBalance.getPrice();
              BigDecimal count = entrustBalance.getCount();
              BigDecimal mulSumFee = price.multiply(count);
              if(activeEntrust.getEntrustType().equals(EntrustConstant.Entrust_Type.SELL)){
                    BigDecimal tradeFeeActive; //收取手续费
                    if(activeEntrust.getTradeRate() != null){
                         tradeFeeActive =  mulSumFee.multiply(activeEntrust.getTradeRate());
                    }else {
                         tradeFeeActive = mulSumFee.multiply(new BigDecimal("0.003"));
                    }
                   if ( activeEntrust.getTradeFee() != null){
                       activeEntrust.setTradeFee(activeEntrust.getTradeFee().add(tradeFeeActive));
                   }else {
                       activeEntrust.setTradeFee(tradeFeeActive);
                   }
                  QueryWrapper<Balance> queryWrapper =new QueryWrapper<>();
                   queryWrapper.eq("user_id",activeEntrust.getMember());
                   queryWrapper.eq("currency",activeEntrust.getTokenCur());
                  Balance balanceTokenCur = balanceMapper.selectOne(queryWrapper);
                  balanceTokenCur.setBlockedBalance(balanceTokenCur.getBlockedBalance().subtract(count));
                  balanceMapper.updateById(balanceTokenCur);


                  QueryWrapper<Balance> wrapperActiveMain = new QueryWrapper<Balance>();
                  wrapperActiveMain.eq("currency", activeEntrust.getMainCur());
                  wrapperActiveMain.eq("user_id", activeEntrust.getMember());
                  Balance balanceTokenMain = balanceMapper.selectOne(wrapperActiveMain);

                  //补齐差额
                  BigDecimal marginPrice = activeEntrust.getPrice().subtract(price);
                  BigDecimal marginFee = marginPrice.multiply(count);

                  balanceTokenMain.setBalance(balanceTokenMain.getBalance().add(mulSumFee).subtract(tradeFeeActive).add(marginFee));
                  balanceMapper.updateById(balanceTokenMain);
              }else {
                 BigDecimal tradeFeeActive;
                 if(activeEntrust.getTradeRate() != null){
                     tradeFeeActive =  count.multiply(activeEntrust.getTradeRate());
                 }else {
                     tradeFeeActive =  count.multiply(new BigDecimal("0.003"));
                 }
                  if (activeEntrust.getTradeFee() != null) {
                      activeEntrust.setTradeFee(activeEntrust.getTradeFee().add(tradeFeeActive));
                  } else {
                      activeEntrust.setTradeFee(tradeFeeActive);
                  }
                  QueryWrapper<Balance> queryWrapper =new QueryWrapper<>();
                  queryWrapper.eq("user_id",activeEntrust.getMember());
                  queryWrapper.eq("currency",activeEntrust.getMainCur());
                  Balance balanceTokenMain = balanceMapper.selectOne(queryWrapper);

                  BigDecimal blockBalanceActive = entrustBalance.getCount().multiply(activeEntrust.getPrice());
                  balanceTokenMain.setBlockedBalance(balanceTokenMain.getBlockedBalance().subtract(blockBalanceActive));

                  //补齐差额
                  BigDecimal marginPrice = activeEntrust.getPrice().subtract(price);
                  BigDecimal marginFee = marginPrice.multiply(count);

                  balanceTokenMain.setBalance(balanceTokenMain.getBalance().add(marginFee));
                  balanceMapper.updateById(balanceTokenMain);

                  QueryWrapper<Balance> wrapperActiveToken = new QueryWrapper<Balance>();
                  wrapperActiveToken.eq("currency", activeEntrust.getTokenCur());
                  wrapperActiveToken.eq("user_id", activeEntrust.getMember());
                  Balance balanceTokenToken = balanceMapper.selectOne(wrapperActiveToken);

                  balanceTokenToken.setBalance(balanceTokenToken.getBalance().add(count).subtract(tradeFeeActive));
                  balanceMapper.updateById(balanceTokenToken);
              }
              if (activeEntrust.getSurplusCount().compareTo(new BigDecimal("0")) == 0) {
                  activeEntrust.setState(EntrustConstant.Order_State.FINAL);
                  EntrustHistory entrustHistory = new EntrustHistory();
                  BeanUtils.copyProperties(activeEntrust, entrustHistory);
                  entrustHistoryMapper.insert(entrustHistory);
                  entrustMapper.deleteById(activeEntrust.getId());
              } else {
                  activeEntrust.setState(EntrustConstant.Order_State.MATCH);
                  entrustMapper.updateById(activeEntrust);
              }
              redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + activeEntrust.getMember());
          }else {
              updateOrderBalanceA(activeEntrust, entrustBalance);
          }
    }


    private void updateOrderBalanceP(Entrust passiveEntrust, EntrustBalance entrustBalance) {
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisRepository.getRedisTemplate());
        boolean lock_coin = redisDistributedLock.lock(CacheConstants.MEMBER_BALANCE_COIN_KEY + passiveEntrust.getMember(), 10000, 50, 100);
        if (lock_coin) {
            BigDecimal price = entrustBalance.getPrice();
            BigDecimal count = entrustBalance.getCount();
            BigDecimal mulSumFee = price.multiply(count);
            if (passiveEntrust.getEntrustType().equals(EntrustConstant.Entrust_Type.SELL)) {
                // 手续费
                BigDecimal tradeFeeActive = new BigDecimal("0");
                if (passiveEntrust.getTradeRate() != null) {
                    tradeFeeActive = mulSumFee.multiply(passiveEntrust.getTradeRate());
                } else {
                    tradeFeeActive = mulSumFee.multiply(new BigDecimal("0.003"));
                }
                if (passiveEntrust.getTradeFee() != null) {
                    passiveEntrust.setTradeFee(passiveEntrust.getTradeFee().add(tradeFeeActive));
                } else {
                    passiveEntrust.setTradeFee(tradeFeeActive);
                }
                QueryWrapper<Balance> wrapperPassiveToken = new QueryWrapper<Balance>();
                wrapperPassiveToken.eq("currency", passiveEntrust.getTokenCur());
                wrapperPassiveToken.eq("user_id", passiveEntrust.getMember());
                Balance balanceTokenCur = balanceMapper.selectOne(wrapperPassiveToken);
                log.info("被动方代币原资产SELL:冻结:" + balanceTokenCur.getCurrency() + "-" + balanceTokenCur.getBlockedBalance());
                log.info("被动方代币原资产SELL:可用:" + balanceTokenCur.getCurrency() + "-" + balanceTokenCur.getBalance());
                balanceTokenCur.setBlockedBalance(balanceTokenCur.getBlockedBalance().subtract(count));
                balanceMapper.updateById(balanceTokenCur);
                log.info("被动方代币原资产SELL:更改后冻结:" + balanceTokenCur.getCurrency() + "-" + balanceTokenCur.getBlockedBalance());
                log.info("被动方代币原资产SELL:更改后可用:" + balanceTokenCur.getCurrency() + "-" + balanceTokenCur.getBalance());
                QueryWrapper<Balance> wrapperPassiveMain = new QueryWrapper<Balance>();
                wrapperPassiveMain.eq("currency", passiveEntrust.getMainCur());
                wrapperPassiveMain.eq("user_id", passiveEntrust.getMember());
                Balance balanceTokenMain = balanceMapper.selectOne(wrapperPassiveMain);
                log.info("被动方主币原资产SELL:冻结:" + balanceTokenMain.getCurrency() + "-" + balanceTokenMain.getBlockedBalance());
                log.info("被动方主币原资产SELL:可用:" + balanceTokenMain.getCurrency() + "-" + balanceTokenMain.getBalance());
                //补齐差额
                BigDecimal marginPrice = passiveEntrust.getPrice().subtract(price);
                BigDecimal marginFee = marginPrice.multiply(count);
                log.info("被被动方主币差额BUY:原价格" + passiveEntrust.getPrice() + "成交价格:" + price + "数量:" + count + "差额:" + marginFee + "手续费:" + tradeFeeActive);
                balanceTokenMain.setBalance(balanceTokenMain.getBalance().add(mulSumFee).subtract(tradeFeeActive).add(marginFee));
                balanceMapper.updateById(balanceTokenMain);
                log.info("被动方主币原资产SELL:更改后冻结:" + balanceTokenMain.getCurrency() + "-" + balanceTokenMain.getBlockedBalance());
                log.info("被动方主币原资产SELL:更改后可用:" + balanceTokenMain.getCurrency() + "-" + balanceTokenMain.getBalance());
            } else {
                // 手续费
                BigDecimal tradeFeeActive = new BigDecimal("0");
                if (passiveEntrust.getTradeRate() != null) {
                    tradeFeeActive = count.multiply(passiveEntrust.getTradeRate());
                } else {
                    tradeFeeActive = count.multiply(new BigDecimal("0.003"));
                }
                if (passiveEntrust.getTradeFee() != null) {
                    passiveEntrust.setTradeFee(passiveEntrust.getTradeFee().add(tradeFeeActive));
                } else {
                    passiveEntrust.setTradeFee(tradeFeeActive);
                }
                QueryWrapper<Balance> wrapperPassiveMain = new QueryWrapper<Balance>();
                wrapperPassiveMain.eq("currency", passiveEntrust.getMainCur());
                wrapperPassiveMain.eq("user_id", passiveEntrust.getMember());
                Balance balanceTokenMain = balanceMapper.selectOne(wrapperPassiveMain);
                log.info("被动方主币原资产BUY:冻结:" + passiveEntrust.getMainCur() + "-" + balanceTokenMain.getBlockedBalance());
                log.info("被动方主币原资产BUY:可用:" + passiveEntrust.getMainCur() + "-" + balanceTokenMain.getBalance());
                BigDecimal blockBalanceActive = entrustBalance.getCount().multiply(passiveEntrust.getPrice());
                balanceTokenMain.setBlockedBalance(balanceTokenMain.getBlockedBalance().subtract(blockBalanceActive));
                //补齐差额
                BigDecimal marginPrice = passiveEntrust.getPrice().subtract(price);
                BigDecimal marginFee = marginPrice.multiply(count);
                log.info("被动方主币差额BUY:原价格" + passiveEntrust.getPrice() + "成交价格:" + price + "数量:" + count + "差额:" + marginFee + "手续费:" + tradeFeeActive);
                balanceTokenMain.setBalance(balanceTokenMain.getBalance().add(marginFee));
                balanceMapper.updateById(balanceTokenMain);
                log.info("被动方主币原资产BUY:更改后冻结:" + balanceTokenMain.getCurrency() + "-" + balanceTokenMain.getBlockedBalance());
                log.info("被动方主币原资产BUY:更改后可用:" + balanceTokenMain.getCurrency() + "-" + balanceTokenMain.getBalance());

                QueryWrapper<Balance> wrapperActiveToken = new QueryWrapper<Balance>();
                wrapperActiveToken.eq("currency", passiveEntrust.getTokenCur());
                wrapperActiveToken.eq("user_id", passiveEntrust.getMember());
                Balance balanceTokenToken = balanceMapper.selectOne(wrapperActiveToken);
                log.info("被动方代币计算结果BUY:" + count + "-手续费:" + tradeFeeActive);
                balanceTokenToken.setBalance(balanceTokenToken.getBalance().add(count).subtract(tradeFeeActive));
                balanceMapper.updateById(balanceTokenToken);
                log.info("被动方代币原资产BUY:更改后冻结:" + balanceTokenToken.getCurrency() + "-" + balanceTokenToken.getBlockedBalance());
                log.info("被动方代币原资产BUY:更改后可用:" + balanceTokenToken.getCurrency() + "-" + balanceTokenToken.getBalance());
            }
            if (passiveEntrust.getSurplusCount().compareTo(new BigDecimal("0")) == 0) {
                passiveEntrust.setState(EntrustConstant.Order_State.FINAL);
                EntrustHistory entrustHistory = new EntrustHistory();
                BeanUtils.copyProperties(passiveEntrust, entrustHistory);
                entrustHistoryMapper.insert(entrustHistory);
                entrustMapper.deleteById(passiveEntrust.getId());
            } else {
                passiveEntrust.setState(EntrustConstant.Order_State.MATCH);
                entrustMapper.updateById(passiveEntrust);
            }
            redisDistributedLock.releaseLock(CacheConstants.MEMBER_BALANCE_COIN_KEY + passiveEntrust.getMember());
        } else {
            updateOrderBalanceP(passiveEntrust, entrustBalance);
        }
    }
}
